package descentFly.chips
{
	import UIFree.ObjectEvent;
	
	import UIUtils.uif_util;
	
	import descentFly.controller.FlyController;
	import descentFly.df_optionsObject;
	import descentFly.df_space;
	import descentFly.df_spaceObject;
	import descentFly.df_utils;
	import descentFly.sound.df_soundManager;
	import descentFly.weaponts.IBullet;
	
	import flash.events.Event;
	import flash.geom.Vector3D;
	
	import space.sp_utils;

	public class df_chip extends df_optionsObject {
		public static const DEFAULT_MAXSPEED : Number = 30;
		public static const DEFAULT_LIVE	 : Number = -1;
		public static const DEFAULT_PATHRATIO: int = 300;
		
		public static const FIELD_MAXSPEED			: String = 'maxSpeed';
		public static const FIELD_WEAPONTS			: String = 'weaponts';
		public static const FIELD_LIVE				: String = 'live';
		public static const FIELD_PATHSPEED			: String = 'pathSpeed';
		public static const FIELD_PATHRATIOTIMER	: String = 'pathRatioTimer';
		public static const FIELD_CONTROLLER		: String = 'controller';
		public static const FIELD_MODELDATA			: String = 'modelData';
		
		//EVENTS		
		public static const UPDATECHIP		: String = 'UPDATECHIP';
		public static const MOVECHIP		: String = 'MOVECHIP';
		public static const BULLETHIT		: String = 'BULLETHIT';
		public static const DESTRUCTION		: String = 'DESTRUCTION';
		public static const IKILLED			: String = 'IKILLED';
		public static const LIVECHANGE		: String = 'LIVECHANGE';
		public static const INITCONTROLLER	: String = 'INITCONTROLLER';
		public static const INITWEAPONTS	: String = 'INITWEAPONTS';
		public static const CHANGEWEAPONT	: String = 'CHANGEWEAPONT';
		
		private var _weaponts		: Array;
		private var _space			: df_space;
		private var _weapont		: df_weapont;
		private var _weapontIndex	: int;
		private var _live			: Number;
		private var _maxLive		: Number;
		private var _controller		: FlyController;
		
		public function df_chip(a_space: df_space, a_options: Object) {
			super(a_options);
			checkOption(FIELD_MAXSPEED, DEFAULT_MAXSPEED);
			checkOption(FIELD_LIVE, DEFAULT_LIVE);
			checkOption(FIELD_PATHSPEED, DEFAULT_MAXSPEED / 4);
			checkOption(FIELD_PATHRATIOTIMER, DEFAULT_PATHRATIO);
			_space	 		= a_space;
			_weapont	 	= null;
			_maxLive		= options.live;
			_live			= _maxLive;
			initialize();
		}
		
		protected function initialize(): void {
			weapontsInitialize();
			_space.addObject(this);
			_space.addEventListener(df_space.CHECKBULLETHIT, doCheckHitBullet);
			controllerInitialize();
		}
		
		override protected function removeEvents():void {
			super.removeEvents();
			_space.removeEventListener(df_space.CHECKBULLETHIT, doCheckHitBullet);
		}
		
		protected function createController(a_class: Object, a_options: Object=null): void {
			_controller = a_class.create(_space.app.stage, _space, a_options);
			_controller.setBody(this);
			currentWeapont = weapontFromID(options.defaultWeapont);
		}
		
		protected function get controller(): FlyController {
			return _controller;
		}
		
		protected function controllerInitialize(): void {
			if (options[FIELD_CONTROLLER]) {
				if (options[FIELD_CONTROLLER] is Class)
					createController(options[FIELD_CONTROLLER]);
				else createController(options[FIELD_CONTROLLER].Class, options[FIELD_CONTROLLER].options);
				dispatchEvent(new Event(INITCONTROLLER));
			}
		}
		
		public function get space(): df_space {
			return _space;
		}
		
		protected function isMyChip(): Boolean {
			return _space.myChip == this;
		}
		
		protected function weapontsInitialize(): void {
			_weaponts = new Array();
			if (options.hasOwnProperty(FIELD_WEAPONTS)) { 
				options.weaponts.forEach(function(item: Object, i: int, arr: Array): void {
					new (item.Class)(This, item.options);
				})
				dispatchEvent(new Event(INITWEAPONTS));
			}
		}
		
		public function rollY(a_roll: Number): void {
			update();
		}

		public function rollX(a_roll: Number): void {
			update();
		}

		public function rollZ(a_roll: Number): void {
			update();
		}
		
		public function moveTo(a_move: Number): void {
			dispatchEvent(new Event(MOVECHIP));
			update();
		}
		
		public function slideTo(a_slide: Number): void {
			dispatchEvent(new Event(MOVECHIP));
			update();
		}
		
		public function get live(): Number {
			return _live;
		}
		
		public function get maxLive(): Number {
			return _maxLive;
		}
		
		public function setLive(a_live: Number, source: Object=null): void {
			if (a_live < 0) a_live = 0;
			if ((live != DEFAULT_LIVE) && (_live != a_live)) {
				_live = a_live;
				dispatchEvent(new Event(LIVECHANGE));
				if (_live ==0 ) destruction(source);
			}
		}
		
		protected function destruction(a_source: Object=null): void {
			dispatchEvent(new ObjectEvent(DESTRUCTION, a_source));
			if (a_source is df_chip) 
				(a_source as df_chip).doIKilled(this);
			dispose();
		}
		
		protected function doIKilled(killed : df_chip): void {
			dispatchEvent(new ObjectEvent(IKILLED, killed));
		}
		
		override public function dispose():void {
			_space.removeObject(this);
			
			if (_controller) _controller.dispose();
			_weaponts.forEach(function(weapont: df_weapont, i: int, arr: Array): void {
				weapont.dispose();
			});
			super.dispose();
		}
		
		public function get keyState(): Object {
			return _controller.keyState;
		}
		
		protected function checkHitBullet(a_bullet: IBullet): Object {
			return null;
		}
		
		private function doCheckHitBullet(e: ObjectEvent): void {
			var bullet: IBullet = e.object as IBullet;
			if (bullet.chip != this) {
				var obj: Object = checkHitBullet(bullet);
				if (obj) bulletHit(bullet, obj);
			}
		}
		
		public function bulletHit(a_bullet: IBullet, hitInfo: Object): void {
			dispatchEvent(new ObjectEvent(BULLETHIT, hitInfo));
			playSound('bullet_hit');
			setLive(live - a_bullet.damage, a_bullet.chip);
/*			if (options.bulletHitSound)
				this.space.dispatchEvent(new ObjectEvent(df_soundManager.SOUNDPLAY, options.bulletHitSound));*/
		}
		
		protected function update(): void {
			//dispatchEvent(new ObjectEvent(UPDATECHIP, this));
		}
		
		public function fire(a_fire: Boolean): Boolean {
			if (_weapont) 
				return _weapont.fire(a_fire);
			return false;
		}
		
		public function weapontFromID(wid: int): df_weapont {
			return df_utils.itemFromID(_weaponts, wid) as df_weapont;
		}
		
		public function get currentWeapont(): df_weapont {
			return _weapont;
		}
		
		public function set currentWeapont(a_weapont: df_weapont): void {
			if ((a_weapont != _weapont) && (_weaponts.indexOf(a_weapont) > -1)) {
//				if (_weapont && _weapont.isFire) _weapont.fire(false);
				_weapont = a_weapont;
				dispatchEvent(new Event(CHANGEWEAPONT));
			}
		}
		
		public function get weapontIndex(): int {
			return _weaponts.indexOf(_weapont);
		}
		
		public function set weapontIndex(a_index: int): void {
			currentWeapont = _weaponts[a_index];
		}
		
		public function get nextWeapont(): int {
			return getNextWeapont(1);
		}
		
		public function get prevWeapont(): int {
			return getNextWeapont(-1);
		}
		
		public function setNextWeapont(add: int): Boolean {
			var index: int = getNextWeapont(add);
			if (index != weapontIndex) {
				weapontIndex = index;
				return true;
			}
			return false;
		}
		
		private function getNextWeapont(add: int): int {
			var curIndex: int = (_weaponts.length + weapontIndex + add) % _weaponts.length;
			while (curIndex != weapontIndex) {
				if (!_weaponts[curIndex].limited || (_weaponts[curIndex].ammo > 0))
					return curIndex;
				curIndex = (_weaponts.length + curIndex + add) % _weaponts.length;
			}
			return weapontIndex;
		}
		
		public function get weapontCount(): int {
			return _weaponts.length;
		}
		
		public function addWeapont(a_weapont: df_weapont): void {
			if (_weaponts.indexOf(a_weapont) == -1) {
				_weaponts.push(a_weapont);
			};
		}
		
		public function attachToVector(v: Vector3D): void {
			
		}
	}
}